/**
 * 
 */
package net.thelostlands.thelostmod.listeners;

import java.util.HashSet;
import java.util.Set;

import net.thelostlands.thelostmod.PermHandler;
import net.thelostlands.thelostmod.Permissions;
import net.thelostlands.thelostmod.LostMod;
import net.thelostlands.thelostmod.Permissions.Perms;
import net.thelostlands.thelostmod.runnable.AfterTeleInvis;
import net.thelostlands.thelostmod.runnable.ResetVisiblesForPlayer;
import net.thelostlands.thelostmod.runnable.UpdateInvisibilityTask;

import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerListener;
import org.bukkit.event.player.PlayerPickupItemEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.player.PlayerTeleportEvent;

/**
 * @author sleaker, faaabio
 *
 */
public class LMPlayerListener extends PlayerListener {
	private LostMod plugin;

	public LMPlayerListener(LostMod plugin) {
		this.plugin = plugin;
	}

	private Set<String> teleports = new HashSet<String>();

	public void onPlayerRespawn(PlayerRespawnEvent event) {
		if (LostMod.useSpout)
			return;
		
		Player player = event.getPlayer();
		String playerName = player.getName();
		if (PermHandler.isInvisible(playerName))
			plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new UpdateInvisibilityTask(player, plugin.adminHandler));


		//Makes it so respawning players can't see invisible players
		plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new ResetVisiblesForPlayer(player, plugin.adminHandler));
	}

	public void onPlayerJoin(PlayerJoinEvent event) {
		Player player = event.getPlayer();
		String playerName = player.getName();
		//Try to load the player object from file
                
		if (Permissions.hasAny(player)) {
			if (PermHandler.loadPlayer(playerName)) {
				String message = ChatColor.RED + "You have the following AdminToggles: ";
				//If this player object is stealthed we don't want to output that they are logging in to everyone.
				if (PermHandler.isStealthed(playerName)) {
					event.setJoinMessage(null);
					message += ChatColor.GREEN + " StealthLog ";
					//Check each player online for permission to receive the login message
					for (Player p : plugin.getServer().getOnlinePlayers()) 
						if (Permissions.has(p, Perms.ALL_MESSAGES)) 
							p.sendMessage(ChatColor.GREEN + playerName + ChatColor.WHITE + " logged in stealthily.");
				} else if (Permissions.has(player, Perms.STEALTH))
					message += ChatColor.RED + " StealthLog ";

				//Colorize our Settings for output
				if (Permissions.has(player, Perms.VANISH)) {
					message += PermHandler.colorize(PermHandler.isInvisible(playerName)) + " Invisible ";
					message += PermHandler.colorize(PermHandler.isNoPickup(playerName)) + " NoPickup ";
				}
				if (Permissions.has(player, Perms.GOD))
					message += PermHandler.colorize(PermHandler.isGod(playerName)) + " GodMode ";
				if (Permissions.has(player, Perms.ADMINMODE))
					message += PermHandler.colorize(PermHandler.isAdminMode(playerName)) + " AdminMode ";

				//Send the player a delayed message of what options they have selected
				plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new DelayedMessage(player, message), 10);

				//Make the player go invisible if they have the toggle
				if (PermHandler.isInvisible(playerName) && !LostMod.useSpout)
					plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new UpdateInvisibilityTask(player, plugin.adminHandler));
			} 
		}

		//Makes it so players can't rejoin the server to see invisible players
		if (!LostMod.useSpout) {
			plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new ResetVisiblesForPlayer(player, plugin.adminHandler));
		}
	}

	public void onPlayerQuit(PlayerQuitEvent event) {
		String playerName = event.getPlayer().getName();
		//Check to see if we should try to save the player object
		if (PermHandler.contains(playerName)) {
			//Attempt to save the player object to file
			PermHandler.savePlayer(playerName);
			//if this player is stealthed then make sure to not output the standard quit message
			if (PermHandler.isStealthed(playerName)) {
				event.setQuitMessage(null);
				//Check each player online for permission to receive the logout message.
				for (Player p : plugin.getServer().getOnlinePlayers())
					if (Permissions.has(p, Perms.ALL_MESSAGES))
						p.sendMessage(ChatColor.GREEN + playerName + ChatColor.WHITE + " logged out stealthily");
			}
		}
	}

	public void onPlayerTeleport (PlayerTeleportEvent event) {
		if (event.isCancelled() || LostMod.useSpout)
			return;

		Player player = event.getPlayer();
		if (PermHandler.isInvisible(player.getName())) {
			if (!event.getFrom().getWorld().equals(event.getTo().getWorld()) || PermHandler.getDistance(event.getFrom(), event.getTo()) > 2500 ) {
				if (!teleports.contains(player.getName())) {
					teleports.add(player.getName());
					//For Invisible players lets teleport them to a special location first if they are a long ways away or on a different world
					Location toLoc = event.getTo();
					//Instead send them to the top of the world in the same chunk
					event.setTo(new Location(toLoc.getWorld(), toLoc.getX(), 127, toLoc.getZ()));

					//Make the player invulnerable - just in case they teleport into walls
					player.setNoDamageTicks(20);
					//Create the actual location we want to send the player to in this teleport.
					plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new AfterTeleInvis(player, toLoc, false, plugin.adminHandler), 10);
					return;
				} else {
					teleports.remove(player.getName());
				}
			}
		}
		//update this players view
		plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new AfterTeleInvis(player, event.getTo(), true, plugin.adminHandler), 8);
		return;


	}

	public void onPlayerPickupItem (PlayerPickupItemEvent event) {
		if (event.isCancelled())
			return;
		//Check if we should straight up disallow the pickup
		if (PermHandler.isNoPickup(event.getPlayer().getName())) 
			event.setCancelled(true);
	}

	//Runnable to send a player a delayed message.
	public class DelayedMessage implements Runnable {
		private String message = null;
		private Player player;
		DelayedMessage(Player player, String message) {
			this.message = message;
			this.player = player;
		}

		public void run() {
			player.sendMessage(message);
		}
	}

}
